Framework.Data = {}
local Initialized = false
FrameworkSettings = {}

DATA_CONSTANT 	= 1 -- This variable cannot be overwritten.
DATA_PERSISTENT = 2 -- Variable is saved.
DATA_PRIORITY	= 4 -- This variable is saved whenever it changes. This also automatically makes it a persistent variable.

function Framework.Data.New( ST_Name, AY_Value, FG_Flags )
	if( !Initialized ) then Framework.Data.Load() end
	if( !FrameworkSettings[ST_Name] ) then
		FrameworkSettings[ST_Name] = {	
			Value = AY_Value,
			Flags = FG_Flags
		}
		if( FG_Flags & DATA_PRIORITY > 0 ) then
			Framework.Data.Save()
		end
	else
		Framework.IO.Print( "[Framework.Data] Attempted to overwrite existing variable '" .. ST_Name .. "'!" )
	end
end

function Framework.Data.Set( ST_Name, AY_Value )
	if( !Initialized ) then Framework.Data.Load() end
	if( !FrameworkSettings[ST_Name] ) then
		Framework.IO.Print( "[Framework.Data] Attempted to set non-existent variable '" .. ST_Name .. "'. Creating blank variable." )
		Framework.Data.New( ST_Name, AY_Value, 0 )
	else
		if( FrameworkSettings[ST_Name].Flags & DATA_CONSTANT > 0 ) then
			Framework.IO.Print( "[Framework.Data] Attempted to set read-only variable '" .. ST_Name .. "'" )
			return
		end
	end
	local Temp = FrameworkSettings[ST_Name]
	FrameworkSettings[ST_Name].Value = AY_Value
	if( FrameworkSettings[ST_Name].Flags & DATA_PRIORITY > 0 ) then Framework.Data.Save() end
	return Temp.Value
end

function Framework.Data.Increment( ST_Name )
	if( !Initialized ) then Framework.Data.Load() end
	Framework.Data.Set( ST_Name, Framework.Data.Get( ST_Name ) + 1 )
end

function Framework.Data.Decrement( ST_Name )
	if( !Initialized ) then Framework.Data.Load() end
	Framework.Data.Set( ST_Name, Framework.Data.Get( ST_Name ) - 1 )
end

function Framework.Data.Get( ST_Name )
	if( !Initialized ) then Framework.Data.Load() end
	if( !FrameworkSettings[ST_Name] ) then
		Framework.IO.Print( "[Framework.Data] Attempted to retrieve non-existent variable '" .. ST_Name .. "'" )
	else
		return FrameworkSettings[ST_Name].Value
	end
end

function Framework.Data.Exists( ST_Name )
	if( !Initialized ) then Framework.Data.Load() end
	return FrameworkSettings[ST_Name] != nil
end

function Framework.Data.Find( AY_Needle )
	if( !Initialized ) then Framework.Data.Load() end
	local t = {}
	for k, v in pairs( FrameworkSettings ) do
		if( k == AY_Needle || (type(k) == "string" && type(AY_Needle) == "string" && k:find( AY_Needle )) ) then
			table.insert( t, k )
		end
	end
	return t
end

function Framework.Data.Modify( ST_Name, FG_Flags )
	if( !Initialized ) then Framework.Data.Load() end
	if( FrameworkSettings[ST_Name] ) then
		FrameworkSettings[ST_Name].Flags = FG_Flags
	end
end

function Framework.Data.Load()
	if( Initialized ) then return end
	Initialized = true
	local Data
	if( SERVER && file.Exists( "Framework/Data/Server.txt" ) ) then
		Data = file.Read( "Framework/Data/Server.txt" )
	elseif( CLIENT && file.Exists( "Framework/Data/Client.txt" ) ) then
		Data = file.Read( "Framework/Data/Client.txt" )
	else
		return
	end
	local b = string.byte( Data:sub(1,1) )
	FrameworkSettings = glon.decode( Data:sub(b) )
end

function Framework.Data.Save()
	if( Initialized ) then -- No point in saving if there's no data.		
		local SavedVars = {}
		local i = 0
		for k, v in pairs( FrameworkSettings ) do
			if( v.Flags >= 2 ) then
				SavedVars[k] = v
				i = i + 1
			end
		end
		if( i == 0 ) then return end
		local Header = "SAVED: " .. os.date( "%x %X" ) .. "\nENTRIES: " .. i .. "\n"
		if( SERVER ) then
			file.Write( "Framework/Data/Server.txt", string.char( Header:len()+2) .. Header .. glon.encode( SavedVars ) )
		else 
			file.Write( "Framework/Data/Client.txt", string.char( Header:len()+2) .. Header .. glon.encode( SavedVars ) )
		end
	end
end

timer.Create( "Framework.Data->TimedSave", 300, 0, Framework.Data.Save ) 
hook.Add( "ShutDown", "Framework.Data->ShutDown", Framework.Data.Save )